// ============================================================================
// Implementation file for Myportmapper.cpp
//
// Solution for CPSC 4780 Fall 2010 Group Project
// Fei Wang
// April 8, 2011
//
// This is a simple portmapper only can handle service register 
// and it can NOT handle de-register a service
// ==========================================================================
#include "ServerSocket.h"
#include "ClientSocket.h"
#include "SocketException.h"
#include "Helper.h"
#include "Info.h"
#include <string>
#include <sstream>
#include <vector>
#include  <cstdio>
using namespace std;

//Global values
//==========================================================================
// a vector of info
//==========================================================================
std::vector<info> infoList;
//==========================================================================
// a vector of IP - address for other machine in the DS
//==========================================================================
std::vector<std::string> ipList;
// ==========================================================================
// function name : find_info
// take a string - service name
// this function return index of looking for info
// if can not find service return -1
//===========================================================================
int find_info(const string & name);

// Start of Program
int main()
{
   int num = 0;
   cout << "Please enter how many neighborhoods I have: ";
   cin >> num;
   if(num > 0)
   {
      cout << "Please enter IP address of my neighborhoods: " << endl;
   }
   for (int i = 0 ; i < num ; ++i)
   {
      cout << "Host " << i + 1 << " :";
      string add = "";
      cin >> add;
      ipList.push_back(add);
   }
   std::cout << "portmapper is running....\n";
   
   try
   {
      // Create the listening socket
      ServerSocket server(10111);
      // Begin waiting for stubs and portmappers
      while (true)
      {
	 // Initialize new sockets for input and output
         ServerSocket *pmap_socket = new ServerSocket(0);
         server.accept(*pmap_socket);
	 cout << "accept new socket" << endl;
	 // Variable Declarations
         std::string request;
         
         // Wait for client request
         svcsock_receive(request,pmap_socket);
        
          // get request from stub to register new service*/
         if(request == "register service -stub")
         {  
            cout << "Received register service request from server stub" << endl;  
	    std::string prog = "";
	    std:: string address = "";
	    std:: string port = "";
	    svcsock_receive(prog,pmap_socket);
            svcsock_receive(address,pmap_socket);
            svcsock_receive(port,pmap_socket);
    
	    if(find_info(prog) == -1)
	    {
               
	       for(unsigned int i = 0 ; i < ipList.size() ;  ++i)
	       {
                 try{
		  ClientSocket * client_socket  = new ClientSocket( ipList[i] , 10111);
		  clntsock_send("register service -portmapper",client_socket);
		  clntsock_send(prog,client_socket) ;
                  clntsock_send(address,client_socket) ;
                  clntsock_send(port,client_socket) ;
                  delete client_socket;
                 }
                 catch(SocketException& e){
                      std::cout << "Exception was caught:" << e.description() << "\n";
                 }
	       }
	       info newservice(prog,address,port);
	       infoList.push_back(newservice);
               svcsock_send("added",pmap_socket);
               cout << "service is registered " << prog << " " << address << " " << port << endl;
	    }
	    else{
              svcsock_send("Error",pmap_socket);
            }
         }
	    //get request from other portmapper to register new service*/
	    else if(request == "register service -portmapper")
	    {
               cout << "Received register service request from another portmapper" << endl;
                std::string prog = "";
                std:: string address = "";
                std:: string port = "";
                svcsock_receive(prog,pmap_socket);
                svcsock_receive(address,pmap_socket);
                svcsock_receive(port,pmap_socket);
                
	       info newservice(prog,address,port);
	       infoList.push_back(newservice);
               cout << "service is registered " << prog << " " << address << " " << port << endl;
	    }
	     // of get request from stub to look at a service*/
	    else if(request == "look up")
	    {
               cout << "Received look up request" << endl;
               svcsock_receive(request,pmap_socket);
	       int pos = find_info(request);
               
	       if(pos == -1)
	       {
                   cout << "Can  NOT find Service" << endl;
                   svcsock_send("None",pmap_socket);
	       }
	       else
	       {
                  cout << "Found Service" <<  endl;
                  svcsock_send("Found",pmap_socket);
                  svcsock_send(infoList[pos].get_address(),pmap_socket);
                  svcsock_send(infoList[pos].get_port(),pmap_socket);

	       }
	    }
	    
	    // Delete all pointers to free memory and release the ports
	    delete pmap_socket;
	    pmap_socket  = NULL;
         }
	 
      }
   // Catch any Exceptions
   catch (SocketException& e)
   {
      std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
      cerr << "Error was in main!" << endl;
   }
   return 0;
}

// ==========================================================================
// this function return index of looking for info
//===========================================================================
int find_info(const string & prog)
{
   int var = -1;
   for(unsigned int i = 0 ; i < infoList.size() ; i ++)
   {
      if(infoList[i].get_prog() == prog)
      {
	 var = i;
         break;
      }
   }
   return var;
}
